home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 3
/
Cream of the Crop 3.iso
/
comm
/
wnos5src.zip
/
SOCKUSER.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-10-03
|
10KB
|
542 lines
#include "global.h"
#include "config.h"
#ifdef ANSIPROTO
#include <stdarg.h>
#endif
#include <conio.h>
#include "mbuf.h"
#include "proc.h"
#include "socket.h"
#ifdef LZW
#include "lzw.h"
#endif
#include "usock.h"
#include "session.h"
#include "nr4.h"
#ifndef EOF
#define EOF (EOF)
#endif
#ifdef SOBUF
#undef SOBUF
#endif
#define SOBUF 768
static int near usvprintf __ARGS((int s,char *fmt, va_list args));
#ifdef XXX
static int near
strlen(char *s)
{
int i = 0;
while(*s++ != '\0')
i++;
return i;
}
#endif
#ifdef XXX
/* Higher-level receive routine, intended for connection-oriented sockets.
* Can be used with datagram sockets, although the sender id is lost.
*/
int
recv(s,buf,len,flags)
int s; /* Socket index */
char *buf; /* User buffer */
int len; /* Max length to receive */
int flags; /* Unused; will eventually select oob data, etc */
{
struct mbuf *bp;
int cnt;
if(len == 0)
return 0; /* Otherwise would be interp as "all" */
if((cnt = recv_mbuf(s,&bp,flags,NULLCHAR,0)) > 0) {
cnt = (int)min(cnt,len);
pullup(&bp,buf,(int16)cnt);
free_p(bp);
}
return cnt;
}
#endif
#ifdef XXX
/* Higher level receive routine, intended for datagram sockets. Can also
* be used for connection-oriented sockets, although from and fromlen are
* ignored.
*/
int
recvfrom(s,buf,len,flags,from,fromlen)
int s; /* Socket index */
char *buf; /* User buffer */
int len; /* Maximum length */
int flags; /* Unused; will eventually select oob data, etc */
char *from; /* Source address, only for datagrams */
int *fromlen; /* Length of source address */
{
struct mbuf *bp;
int cnt;
if((cnt = recv_mbuf(s,&bp,flags,from,fromlen)) > 0) {
cnt = (int)min(cnt,len);
pullup(&bp,buf,(int16)cnt);
free_p(bp);
}
return cnt;
}
#endif
/* High level send routine */
int
send(
int s, /* Socket index */
char *buf, /* User buffer */
int len, /* Length of buffer */
int flags) /* Unused; will eventually select oob data, etc */
{
struct mbuf *bp;
char sock[MAXSOCKSIZE];
int i = MAXSOCKSIZE;
if(getpeername(s,sock,&i) == EOF)
return EOF;
bp = qdata(buf,(int16)len);
return send_mbuf(s,bp,flags,sock,i);
}
/* High level send routine, intended for datagram sockets. Can be used on
* connection-oriented sockets, but "to" and "tolen" are ignored.
*/
int
sendto(
int s, /* Socket index */
char *buf, /* User buffer */
int len, /* Length of buffer */
int flags, /* Unused; will eventually select oob data, etc */
char *to, /* Destination, only for datagrams */
int tolen) /* Length of destination */
{
struct mbuf *bp = qdata(buf,(int16)len);
return send_mbuf(s,bp,flags,to,tolen);
}
/* Receive a newline-terminated line from a socket, returning # chars read.
* The end-of-line sequence is recognized and translated into a single '\n'.
*/
int
recvline(
int s, /* Socket index */
char *buf, /* User buffer */
unsigned len) /* Length of buffer */
{
int c, cnt = 0;
while(len-- > 1) {
if((c = recvchar(s)) == EOF){
cnt = EOF;
break;
}
if(buf != NULLCHAR) {
*buf++ = c;
}
cnt++;
if(uchar(c) == '\n') {
break;
}
}
if(buf != NULLCHAR) {
*buf = '\0';
}
return cnt;
}
#if defined(ANSIPROTO)
/* Do printf on a user socket */
int
usprintf(int s,char *fmt,...)
{
va_list args;
int len;
va_start(args,fmt);
len = usvprintf(s,fmt,args);
va_end(args);
return len;
}
/* Printf on standard output socket */
int
tprintf(char *fmt,...)
{
va_list args;
int len;
va_start(args,fmt);
len = usvprintf(Curproc->output,fmt,args);
va_end(args);
return len;
}
/* The guts of printf, uses variable arg version of sprintf */
static int near
usvprintf(int s,char *fmt,va_list args)
{
int i, len;
char *cp;
if(strchr(fmt,'%') == NULLCHAR) {
/* No args, so we don't need vsprintf() */
len = strlen(fmt);
cp = fmt;
} else {
char buf[SOBUF];
/* Use a default value that is hopefully longer than the
* biggest output string we'll ever print (!)
*/
cp = buf;
vsprintf(cp,fmt,args);
len = strlen(cp);
}
i = len;
while(i-- > 0) {
if(usputc(s,*cp++) == EOF) {
return EOF;
}
}
return len;
}
#else
/*VARARGS*/
/* Printf to standard output socket */
int
tprintf(fmt,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12)
char *fmt; /* Message format */
int arg1,arg2,arg3; /* Arguments */
int arg4,arg5,arg6;
int arg7,arg8,arg9;
int arg10,arg11,arg12;
{
return usprintf(Curproc->output,fmt,arg1,arg2,arg3,arg4,arg5,arg6,
arg7,arg8,arg9,arg10,arg11,arg12);
}
/* Printf to socket. Doesn't use ANSI vsprintf */
int
usprintf(s,fmt,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12)
int s; /* Socket index */
char *fmt; /* Message format */
int arg1,arg2,arg3; /* Arguments */
int arg4,arg5,arg6;
int arg7,arg8,arg9;
int arg10,arg11,arg12;
{
int i, len;
char *cp;
if(strchr(fmt,'%') == NULLCHAR){
/* No args, so we don't need vsprintf() */
char *buf1 = fmt;
len = strlen(buf1);
cp = buf1;
} else {
/* Use a default value that is hopefully longer than the
* biggest output string we'll ever print (!)
*/
char buf[SOBUF];
cp = buf;
sprintf(cp,fmt,arg1,arg2,arg3,arg4,arg5,arg6,arg7,
arg8,arg9,arg10,arg11,arg12);
len = strlen(cp);
}
i = len;
while(i-- > 0) {
if(usputc(s,*cp++) == EOF) {
return EOF;
}
}
return len;
}
#endif
/* Buffered putchar to a socket */
int
usputc(int s,char c)
{
struct mbuf *bp;
struct usock *up = itop(s);
if(up == NULLUSOCK) {
return EOF;
}
if(up->obuf == NULLBUF) {
/* Allocate a buffer of appropriate size */
#ifdef NETROM
switch(up->type){
case TYPE_NETROML4:
up->obuf = alloc_mbuf(Nr_iface->mtu);
break;
default:
up->obuf = alloc_mbuf(SOBUF);
break;
}
#else
up->obuf = alloc_mbuf(SOBUF);
#endif
}
bp = up->obuf;
if(c == '\n' && (up->flag & SOCK_ASCII)) {
char *cp;
/* Translate into appropriate end-of-line sequence */
for(cp = up->eol; *cp != '\0'; cp++) {
#ifdef LZW
if(up->zout == NULLLZW) {
bp->data[bp->cnt++] = *cp;
} else {
lzwencode(s,*cp);
}
#else
bp->data[bp->cnt++] = *cp;
#endif
}
} else {
#ifdef LZW
if(up->zout == NULLLZW) {
bp->data[bp->cnt++] = c;
} else {
lzwencode(s,c);
}
#else
bp->data[bp->cnt++] = c;
#endif
}
/* Always leave enough room for an eol sequence in the next call */
if((c == up->flush && up->flush != EOF) || bp->cnt >= bp->size - 9) {
if(usflush(s) == EOF) {
return EOF;
}
}
return (int)uchar(c);
}
int
usputs(int s,char *x)
{
int len = 0;
while(*x != '\0') {
if(usputc(s,*x++) == EOF) {
return EOF;
}
len++;
}
return len;
}
#ifdef XXX
/* Put a character to standard output socket */
int
tputc(char c)
{
return usputc(Curproc->output,c);
}
#endif
/* Put a string to standard output socket */
int
tputs(char *s)
{
int len = 0;
while(*s != '\0') {
if(usputc(Curproc->output,*s++) == EOF) {
return EOF;
}
len++;
}
return len;
}
/* Read a raw character from a socket with stream buffering. */
int
rrecvchar(int s) /* Socket index */
{
struct usock *up;
if((up = itop(s)) != NULLUSOCK) {
#ifdef LZW
int c;
if(up->zin != NULLLZW && (c = lzwdecode(up)) != EOF) {
return c;
}
/* Replenish if necessary */
if(up->ibuf == NULLBUF && recv_mbuf(s,&up->ibuf,0,NULLCHAR,0) <= 0) {
return EOF;
}
if(up->zin != NULLLZW) {
if((c = lzwdecode(up)) != EOF) {
return c;
} else {
return rrecvchar(s); /* need to replenish */
}
}
#else
/* Replenish if necessary */
if(up->ibuf == NULLBUF && recv_mbuf(s,&up->ibuf,0,NULLCHAR,0) <= 0) {
return EOF;
}
#endif
return PULLCHAR(&up->ibuf); /* Returns EOF if eof */
}
return EOF;
}
/* This function recognizes the end-of-line sequence for the stream
* and translates it into a single '\n'.
*/
int
recvchar(int s) /* Socket index */
{
struct usock *up;
if((up = itop(s)) != NULLUSOCK) {
int c;
if((c = rrecvchar(s)) != up->eol[0] || !(up->flag & SOCK_ASCII)) {
return c;
}
/* This is the first char of a eol sequence. If the eol sequence
* is more than one char long, eat the next character in the
* input stream.
*/
if(up->eol[1] != '\0') {
rrecvchar(s);
}
return '\n';
}
return EOF;
}
/* Flush output on a socket stream */
int
usflush(int s)
{
struct usock *up = itop(s);
if(up != NULLUSOCK) {
struct mbuf *bp = up->obuf;
if(bp != NULLBUF) {
#ifdef LZW
if(up->zout != NULLLZW) {
lzwflush(up);
}
#endif
up->obuf = NULLBUF;
return send_mbuf(s,bp,0,NULLCHAR,0);
}
return 0;
}
return EOF;
}
/* Flush output socket */
void
tflush()
{
usflush(Current->output);
}
/* Print prompt and read one character */
int
keywait(
char *prompt, /* Optional prompt */
int flush) /* Flush queued input? */
{
int c, i;
if(flush && socklen(Curproc->input,1) != 0) {
recv_mbuf(Curproc->input,NULLBUFP,0,NULLCHAR,0); /* flush */
}
if(prompt == NULLCHAR) {
prompt = "Hit enter to continue";
}
tputs(prompt);
usflush(Curproc->output);
c = recvchar(Curproc->input);
/* Get rid of the prompt */
for(i = strlen(prompt); i != 0; i--) {
tputs("\b \b");
}
usflush(Curproc->output);
return c;
}
/* Set the end-of-line sequence on a socket */
int
seteol(int s,char *seq)
{
struct usock *up;
if((up = itop(s)) != NULLUSOCK) {
if(seq != NULLCHAR) {
strncpy(up->eol,seq,sizeof(up->eol));
} else {
*up->eol = '\0';
}
return 0;
}
return EOF;
}
/* Enable/disable eol translation, return previous state */
int
sockmode(int s,int mode)
{
struct usock *up;
if((up = itop(s)) != NULLUSOCK) {
int prev = up->flag;
usflush(s);
switch(mode){
case SOCK_BINARY:
case SOCK_ASCII:
up->flag = mode;
break;
}
return prev;
}
return EOF;
}
/* Specify the character to trigger automatic output buffer
* flushing, or EOF to disable it. Return the previous setting.
*/
int
setflush(int s,int c)
{
struct usock *up;
usflush(s);
if((up = itop(s)) != NULLUSOCK) {
int old = up->flush;
up->flush = c;
return old;
}
return EOF;
}